﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ManagerCtr : IGameLogic
{
    private MonoBehaviour root;

    private List<IManager> m_ManagerList = new List<IManager>();
    private List<IManager> m_ManagerInitedList = new List<IManager>();
    private List<IUpdate> m_UpdateList = new List<IUpdate>();
    private List<IFixedUpdate> m_FiexdUpdateList = new List<IFixedUpdate>();
    private List<ILateUpdate> m_LateUpdateList = new List<ILateUpdate>();
    private List<ISlowUpdate> m_SlowUpdateList = new List<ISlowUpdate>();

    private const float SLOW_DELTA_TIME = 1f;
    private float curSlowDeltaTime = 0;
    private void SetRoot(MonoBehaviour mono)
    {
        root = mono;
    }

    #region interface
    public void OnAwake()
    {

    }
    public void OnInit(LogicWeight weight)
    {
        IManager manager;
        for (int i = 0, len = m_ManagerList.Count; i < len; i++)
        {
            manager = m_ManagerList[i];

            if (!m_ManagerInitedList.Contains(manager) && (int)manager.logicWeight >= (int)weight)
            {
                if (manager is IUpdate)
                    m_UpdateList.Add(manager as IUpdate);
                if (manager is ILateUpdate)
                    m_LateUpdateList.Add(manager as ILateUpdate);
                if (manager is IFixedUpdate)
                    m_FiexdUpdateList.Add(manager as IFixedUpdate);
                if (manager is ISlowUpdate)
                    m_SlowUpdateList.Add(manager as ISlowUpdate);

                manager.OnInit();
                m_ManagerInitedList.Add(manager);
            }
        }
    }
    public void OnUpdate()
    {
        if (m_UpdateList == null || m_UpdateList.Count < 1) return;

        var deltaTime = GameTime.GDeltaTime;
        curSlowDeltaTime += deltaTime;
        if (curSlowDeltaTime >= SLOW_DELTA_TIME)
        {
            for (int i = 0; i < m_SlowUpdateList.Count; i++)
            {
                m_SlowUpdateList[i].OnSlowUpdate(SLOW_DELTA_TIME);
            }
            curSlowDeltaTime -= SLOW_DELTA_TIME;
        }

        for (int i = 0; i < m_UpdateList.Count; i++)
        {
            m_UpdateList[i].OnUpdate(deltaTime);
        }
    }
    public void OnLateUpdate() {
        if (m_LateUpdateList == null || m_LateUpdateList.Count < 1) return;
        for (int i = 0; i < m_FiexdUpdateList.Count; i++)
        {
            m_LateUpdateList[i].OnLateUpdate(GameTime.GDeltaTime);
        }
    }
    public void OnFixedUpdate()
    {
        if (m_FiexdUpdateList == null || m_FiexdUpdateList.Count < 1) return;
        for (int i = 0; i < m_FiexdUpdateList.Count; i++)
        {
            m_FiexdUpdateList[i].OnFixedUpdate(GameTime.GDeltaTime);
        }
    }
    public void OnPause(bool pause)
    {
        if (m_ManagerInitedList == null || m_ManagerInitedList.Count < 1) return;
        for (int i = 0 ,len = m_ManagerInitedList.Count; i < len; i++)
        {
            m_ManagerInitedList[i].OnPause(pause);
        }
    }
    public void OnFocus(bool focus)
    {
        if (m_ManagerInitedList == null || m_ManagerInitedList.Count < 1) return;
        for (int i = 0 ,len = m_ManagerInitedList.Count; i < len; i++)
        {
            m_ManagerInitedList[i].OnFocus(focus);
        }
    }
    public void OnReset(LogicWeight weight)
    {
        IManager manager;
        int i = m_ManagerInitedList.Count;
        while (--i > -1)
        {
            manager = m_ManagerInitedList[i];
            if ((int)manager.logicWeight <= (int)weight)
            {
                if (manager is IUpdate)
                    m_UpdateList.Remove(manager as IUpdate);
                if (manager is ILateUpdate)
                    m_LateUpdateList.Remove(manager as ILateUpdate);
                if (manager is IFixedUpdate)
                    m_FiexdUpdateList.Remove(manager as IFixedUpdate);

                manager.OnReset();
                m_ManagerInitedList.RemoveAt(i);
                  
            }
        }
    }
    public void OnEnterScene()
    {
        if (m_ManagerInitedList == null || m_ManagerInitedList.Count < 1) return;
        for (int i = 0, len = m_ManagerInitedList.Count; i < len; i++)
        {
            m_ManagerInitedList[i].OnEnterScene();
        }
    }
    public void OnExitScene()
    {
        if (m_ManagerInitedList == null || m_ManagerInitedList.Count < 1) return;
        for (int i = 0, len = m_ManagerInitedList.Count; i < len; i++)
        {
            m_ManagerInitedList[i].OnExitScene();
        }
    }
    public void OnDestroy()
    {
        for (int i = m_ManagerList.Count - 1; i >= 0;i--)
        {
            m_ManagerList[i].OnDestroy();
        }
        m_ManagerList.Clear();
        m_ManagerInitedList.Clear();
    }
    #endregion
    private void RegisterManager<T>(Manager<T> manager, LogicWeight weight = LogicWeight.GAME) where T : class, new()
    {
        if (manager != null)
        {
            manager.SetMono(root, weight);
            manager.OnAwake();
            m_ManagerList.Add(manager);
        }

    }
}
